package day4;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//通过反射编写一个任意对象调用任意方法
public class TestInvokeMethod {
    //method(方法名，形参class[])
    //method.invoke(对象，实参...)
    //参数1：调用方法的对象   参数2：方法名称
    //参数3：方法调用传递的实参
    //返回值：表示方法的返回值
    //bug:如果调用了基本类型参数的方法，他会自动装箱，导致方法不存在...
    public static Object base(Object o,String name,Object...params){
        Object value = null;
        try {
            Class c =o.getClass();
            Class[] args = new Class[params.length];
            for (int i = 0; i < params.length; i++) {
                args[i] = params[i].getClass();
            }
            Method m = c.getDeclaredMethod(name,args);
            m.setAccessible(true);
            value = m.invoke(o, params);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return value;
    }

    //bug:虽然搞定了基本类型参数的bug 但是如果方法重载了呢？
    public static Object base2(Object o,String name,Object ...params){
        Class c = o.getClass();
        Class[] args = null;
        for (Method m:c.getDeclaredMethods()){
            if (m.getName().equals(name)){
                args = m.getParameterTypes();
            }
        }
        Object value = null;
        try {
            Method m = c.getDeclaredMethod(name,args);
            m.setAccessible(true);
            value = m.invoke(o, params);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return value;
    }
    public static void main(String[] args) {
        Student s = new Student();
        Object value = TestInvokeMethod.base(s,"math",10,20);
        System.out.println(value);

        Teacher t =new Teacher();
        Object value2 = TestInvokeMethod.base2(t,"sum",90,80);
        System.out.println(value2);
    }
}
